package se.kth.ik2200.carenet_2012;

/**
 * Created with IntelliJ IDEA.
 * User: Ruslan Mukhammadov
 * Date: November 12, 2012
 * Time: 4:01 PM
 * To change this template use File | Settings | File Templates.
 */

import javax.bluetooth.RemoteDevice;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.Date;

/**
 * This application is being written specifically for
 * Nonin Onyx II 9560 models  and going to be tested.
 * It may or may not work other Nonin models.
 */
public class NoninOnyx extends Device {

    public static final String DEVICE_MODEL = "Nonin Onyx II 9560";

    /**
     * Nonin sensor has several data formats (#2, #7, #8 and #13).
     * By default it uses #13 data format.In order to exchange the
     * data, first proper data format has to be sent to the device
     * as a command  and  the device  will response with some data
     * according  to the data format.  Current variable in 6 bytes
     * represents #8 data format.  In #8 data format, Nonin device
     * sends 4 byte length data each time. They are:
     *
     * 1. Pulse Rate MSB
     * 2. Pulse Rate LSB
     * 3. SpO2
     * 4. Status
     */
    private final byte[] DATA_FORMAT_SELECTION = new byte[] {0x02, 0x70, 0x02, 0x02, 0x08, 0x03};

    private RemoteDevice remoteDevice;

    @Override
    public String getDeviceDescription() {
        return "The Onyx® II, the most trusted name in fingertip pulse oximetry, is now integrated with Bluetooth " +
                "Wireless Technology allowing patients to take vital signs anytime, anywhere. Breakthrough devices " +
                "such as the Onyx II, Model 9560 will enable clinicians to remotely monitor patients with chronic " +
                "diseases such as Chronic Obstructive Pulmonary Disease (COPD), Congestive Heart Failure (CHF) or " +
                "Asthma. Wireless oximetry gives patients a new level of freedom and control.";
    }

    @Override
    public String getDeviceModel() {
        return DEVICE_MODEL;
    }

    @Override
    public String getDeviceName() throws IOException {
        return extractDeviceName(remoteDevice);
    }

    @Override
    public String getDevicePinCode() {
        return "199646";
    }

    @Override
    public RemoteDevice getInstance() {
        return remoteDevice;
    }

    @Override
    public void readDevice(String service, String userName)
            throws InterruptedException, IOException, NoSuchAlgorithmException, KeyManagementException {
        /**
         * RFCOMM connection should be initiated and established with Nonin
         * sensor to read data. There is no need for OBEX connection.
         */
        StreamConnection rfCommConnection = (StreamConnection) Connector.open(service);

        /**
         * By default Nonin sensor uses #13 format that transmit packets
         * every 1.75 seconds.  We are changing the data format from #13
         * to #8 that sends packets every 1 second.
         */
        OutputStream outputStream = rfCommConnection.openOutputStream();
        outputStream.write(DATA_FORMAT_SELECTION);
        outputStream.close();

        InputStream inputStream = rfCommConnection.openInputStream();

        /**
         * We have to receive packets from sensor continuously
         * until it stops to transmit.
         */
        while (true) {
            /**
             * In #8 format, data arrives every 1 second. So it does
             * not make sense getting the same  data again and again
             * during 1 second.Nonin sensor by default uses #13 data
             * format, however we are using another #8 data format.
             *
             * In #13 data format,Nonin sensor will transmit packets
             * every 3/4 seconds and in #8 format it will send every
             * 1 second.
             */
            Thread.sleep(1000);

            byte[] packet = getBytesFromInputStream(inputStream);

            /**
             * If the sensor stops to transmit packets, maybe because
             * patient pulled out finger from it or switched it off.
             */
            if (packet.length == 0) {
                Log.printTitle("Packets transmission is stopped!");
                inputStream.close();

                break;
            }

            String date = new Date().toString();
            String log = "Received " + packet.length + " bytes in #8 data format. Date: " + date;
            Log.printOrdinaryLog(log);

            // There is no need to read formats other than #8.
            if (packet.length == 4) {
                String pulseRate = String.valueOf(packet[1]);
                String sp02 = String.valueOf(packet[2]);

                Log.printWithoutLine("Heart Pulse Rate: " + pulseRate);
                Log.printOrdinaryLog("      SpO2: " + sp02 + "\n");

                SensorData data = getDeviceData(userName);
                data.setPulseRate(pulseRate);
                data.setSp02(sp02);

                DataTransmissionHandler.sendDataToWebServer(data);
            }
        }
    }

    @Override
    public void setInstance(RemoteDevice remoteDevice) {
        this.remoteDevice = remoteDevice;
    }
}
